package cn.yangliu.comm;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import cn.yangliu.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

/**
 * @author Xiong Hao
 */
@RestControllerAdvice
@Slf4j
public class WebExceptionHandler {


    /**
     * 全局未知异常统一处理
     */
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.OK)
    public JsonResult<Object> exception(HttpServletRequest request, Exception exception) {

        /**
         * 内部异常
         */
        if (exception instanceof BizException) {
            BizException e = (BizException) exception;
            return JsonResult.getInstance(e.getCode(), e.getMsg());
        }
        log.error(exception.getMessage(), exception);

        /**
         * 406
         */
        if (exception instanceof HttpMediaTypeNotSupportedException) {
            return JsonResult.getInstance(HttpStatus.NOT_ACCEPTABLE.value(),
                    "Content-Type仅支持" + MediaType.APPLICATION_JSON_UTF8_VALUE);
        }

        /**
         * 参数异常
         */
        if (exception instanceof BindException) {
            BindException e = (BindException) exception;
            BindingResult bindingResult = e.getBindingResult();
            List<ObjectError> allErrors = bindingResult.getAllErrors();
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < allErrors.size(); i++) {
                ObjectError error = allErrors.get(i);
                sb.append(error.getDefaultMessage());
                if (allErrors.size() != (i + 1)) {
                    sb.append(",");
                }
            }
            String requestURI = request.getRequestURI();
            log.info("请求url: " + requestURI + " , 校验结果: " + sb.toString());
            return JsonResult.getInstance(HttpStatus.BAD_REQUEST.value(), sb.toString());
        }

        /**
         * 403异常
         */
        if (exception instanceof AccessDeniedException) {
            return JsonResult.getInstance(HttpStatus.FORBIDDEN.value(), "没有权限访问该资源");
        }

        /**
         * 405异常
         */
        if (exception instanceof HttpRequestMethodNotSupportedException) {
            String method = request.getMethod();
            return JsonResult.getInstance(HttpStatus.METHOD_NOT_ALLOWED.value(), "不支持" + method + "方式请求");
        }

        /**
         * 参数转换异常
         */
        if (exception instanceof MethodArgumentTypeMismatchException) {
            MethodArgumentTypeMismatchException e = (MethodArgumentTypeMismatchException) exception;
            return JsonResult.getInstance(HttpStatus.BAD_REQUEST.value(), e.getValue() + "不能转换为" + e.getName());
        }

        /**
         * 500异常
         */
        return JsonResult.getInstance(HttpStatus.INTERNAL_SERVER_ERROR.value(), "未知异常,请联系管理员");
    }

}